<!--
 * @FilePath: /my-map-demo/src/views/spatial-analysis/NetworkAnalysis.vue
 * @Author: 张文鑫
 * @Date: 2024-12-30 11:26:35
 * @Description: 
-->
<template>
  <div class="network-analysis">
    <el-card class="analysis-panel">
      <template #header>
        <div class="card-header">
          <span>网络分析</span>
        </div>
      </template>

      <el-form :model="formData" label-width="100px">
        <el-form-item label="分析类型">
          <el-select v-model="formData.analysisType" placeholder="选择分析类型">
            <el-option label="最短路径" value="shortestPath" />
            <el-option label="服务区域" value="serviceArea" />
            <el-option label="最近设施" value="closestFacility" />
          </el-select>
        </el-form-item>

        <el-form-item label="起点">
          <div class="coordinate-input">
            <el-input v-model="formData.startPoint" placeholder="点击地图选择或输入坐标" readonly />
            <el-button type="primary" @click="setPointMode('start')">
              <el-icon><Location /></el-icon>
            </el-button>
          </div>
        </el-form-item>

        <el-form-item label="终点">
          <div class="coordinate-input">
            <el-input v-model="formData.endPoint" placeholder="点击地图选择或输入坐标" readonly />
            <el-button type="primary" @click="setPointMode('end')">
              <el-icon><Location /></el-icon>
            </el-button>
          </div>
        </el-form-item>

        <el-form-item label="交通方式">
          <el-select v-model="formData.travelMode" placeholder="选择交通方式">
            <el-option label="驾车" value="driving" />
            <el-option label="步行" value="walking" />
            <el-option label="骑行" value="cycling" />
          </el-select>
        </el-form-item>

        <el-form-item>
          <el-button-group>
            <el-button type="primary" @click="performNetworkAnalysis" :disabled="!isAnalysisReady">
              执行分析
            </el-button>
            <el-button type="warning" @click="clearAnalysis">清除分析</el-button>
          </el-button-group>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup>
import { reactive, ref, computed, onMounted, onUnmounted, inject } from "vue";
import { Location } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import Feature from "ol/Feature";
import Point from "ol/geom/Point";
import LineString from "ol/geom/LineString";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Style, Stroke, Circle, Fill } from "ol/style";
import { transform } from "ol/proj";

const map = inject("map");
const formData = reactive({
  analysisType: "shortestPath",
  startPoint: "",
  endPoint: "",
  travelMode: "driving",
});

let currentMode = ref(null);
let vectorLayer = null;
let vectorSource = null;

// 初始化矢量图层
const initVectorLayer = () => {
  vectorSource = new VectorSource();
  vectorLayer = new VectorLayer({
    source: vectorSource,
    style: (feature) => {
      const type = feature.get("type");
      if (type === "point") {
        return new Style({
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: feature.get("pointType") === "start" ? "#67C23A" : "#F56C6C",
            }),
          }),
        });
      } else if (type === "route") {
        return new Style({
          stroke: new Stroke({
            color: "#3388ff",
            width: 6,
          }),
        });
      }
    },
  });
  map.addLayer(vectorLayer);
};

// 计算是否可以执行分析
const isAnalysisReady = computed(() => {
  return formData.startPoint && formData.endPoint;
});

// 设置点位模式
const setPointMode = (mode) => {
  currentMode.value = mode;
  ElMessage.info(`请在地图上点击选择${mode === "start" ? "起点" : "终点"}位置`);
};

// 地图点击事件处理
const handleMapClick = (evt) => {
  if (!currentMode.value) return;

  const coordinate = transform(evt.coordinate, "EPSG:3857", "EPSG:4326");
  const point = new Feature({
    geometry: new Point(transform(coordinate, "EPSG:4326", "EPSG:3857")),
    type: "point",
    pointType: currentMode.value,
  });

  // 移除同类型的旧点
  const features = vectorSource.getFeatures();
  features.forEach((feature) => {
    if (feature.get("pointType") === currentMode.value) {
      vectorSource.removeFeature(feature);
    }
  });

  vectorSource.addFeature(point);
  formData[`${currentMode.value}Point`] = coordinate.join(",");
  currentMode.value = null;
};

// 执行网络分析
const performNetworkAnalysis = () => {
  try {
    const start = formData.startPoint.split(",").map(Number);
    const end = formData.endPoint.split(",").map(Number);

    // 创建路线要素
    const routeCoords = [transform(start, "EPSG:4326", "EPSG:3857"), transform(end, "EPSG:4326", "EPSG:3857")];

    const routeFeature = new Feature({
      geometry: new LineString(routeCoords),
      type: "route",
    });

    // 移除旧路线
    const features = vectorSource.getFeatures();
    features.forEach((feature) => {
      if (feature.get("type") === "route") {
        vectorSource.removeFeature(feature);
      }
    });

    vectorSource.addFeature(routeFeature);

    // 调整视图以显示完整路线
    map.getView().fit(routeFeature.getGeometry(), {
      padding: [50, 50, 50, 50],
    });

    ElMessage.success("分析完成");
  } catch (error) {
    ElMessage.error("分析失败：" + error.message);
  }
};

// 清除分析结果
const clearAnalysis = () => {
  if (vectorSource) {
    vectorSource.clear();
  }
  formData.startPoint = "";
  formData.endPoint = "";
  currentMode.value = null;
  ElMessage.success("已清除分析结果");
};

// 组件挂载时初始化
onMounted(() => {
  if (map) {
    initVectorLayer();
    map.on("click", handleMapClick);
  }
});

// 组件卸载时清理
onUnmounted(() => {
  if (map) {
    map.un("click", handleMapClick);
    if (vectorLayer) {
      map.removeLayer(vectorLayer);
    }
  }
});
</script>

<style scoped>
.network-analysis {
  padding: 15px;
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 1000;
}

.analysis-panel {
  max-width: 400px;
  background-color: rgba(255, 255, 255, 0.95);
}

.card-header {
  font-weight: bold;
}

.coordinate-input {
  display: flex;
  gap: 10px;
}

.coordinate-input .el-input {
  flex: 1;
}
</style>
